import { and, desc, eq, gt, max, type SQL } from "drizzle-orm";
import z from "zod";
import { getAllTests, getReportSummary } from "../lib/allure";
import { db } from "../lib/db";
import { getDateRangeStartStamp } from "../lib/utils";
import { reports } from "../schemas/reports";
import { tests } from "../schemas/tests";
import type { TaskLocator } from "../types/allure";

export const QueryReportsSchema = z.object({
  name: z.string().min(1).optional(),
  range: z.enum(["year", "quarter", "month"]).default("month"),
});

export type QueryReportsParams = z.infer<typeof QueryReportsSchema>;

export async function syncReport(task: TaskLocator) {
  const report = await getReportSummary(task);
  const existing = await db
    .select()
    .from(reports)
    .where(and(eq(reports.name, report.name), eq(reports.number, report.number)));

  if (existing.length > 0) {
    return;
  }
  const [newReport] = await db.insert(reports).values(report).returning({ reportId: reports.id });
  const data = await getAllTests({ reportId: newReport.reportId, task });
  await db.insert(tests).values(data);
  return report;
}

export async function getReports(params: QueryReportsParams) {
  const { name, range } = params;

  const filters: SQL[] = [];

  if (name) {
    filters.push(eq(reports.name, name));
  }

  const start = getDateRangeStartStamp(range);
  filters.push(gt(reports.start, start));

  return await db
    .select()
    .from(reports)
    .where(and(...filters))
    .orderBy(desc(reports.start));
}

export async function getReportNames() {
  return await db
    .select({
      name: reports.name,
      latestStart: max(reports.start).as("latestStart"),
    })
    .from(reports)
    .groupBy(reports.name)
    .orderBy(desc(max(reports.start)));
}

export async function getReportById(id: string) {
  return await db.query.reports.findFirst({
    where: (reports, { eq }) => eq(reports.id, id),
  });
}
